import logging
import os
from logging.handlers import TimedRotatingFileHandler

class Logger:
    """
    日志记录器封装类，支持控制台输出 + 文件输出（按天滚动）
    """

    level_relations = {
        'debug': logging.DEBUG,
        'info': logging.INFO,
        'warning': logging.WARNING,
        'error': logging.ERROR,
        'crit': logging.CRITICAL
    }

    def __init__(self, root_path, log_name='app', level='info',
                 fmt='%(asctime)s [%(levelname)s] %(filename)s:%(lineno)d - %(message)s',
                 console_output=True, when='midnight', backup_count=7):
        """
        :param root_path: 项目根目录
        :param log_name: 日志模块名称（会作为日志文件名前缀）
        :param level: 日志级别
        :param fmt: 日志格式
        :param console_output: 是否输出到控制台
        :param when: 滚动周期（如 'midnight' 表示每天滚动）
        :param backup_count: 最多保留最近多少天备份文件
        """
        self.root_path = root_path
        self.log_name = log_name
        self.level = level
        self.fmt = fmt
        self.console_output = console_output
        self.when = when
        self.backup_count = backup_count

        # 创建 logger
        self.logger = logging.getLogger(log_name)
        self.logger.setLevel(self.level_relations.get(level, logging.INFO))

        # 防止重复添加 handler
        if not self.logger.handlers:
            self._add_handlers()

    def _add_handlers(self):
        """
        添加日志处理器
        原因:
            假设你在一个模块中配置了日志记录器，并且在其他模块中也引用了这个日志记录器。
            如果你不加限制地每次都给它添加一个新的处理器，那么每当导入一次该模块时，
            都会为日志记录器增加一个额外的处理器。结果就是，原本应该只输出一次的日志信息会被多次输出。
        """
        formatter = logging.Formatter(self.fmt)

        # 文件处理器：按天滚动
        log_dir = os.path.join(self.root_path, 'logs')
        os.makedirs(log_dir, exist_ok=True)
        log_file = os.path.join(log_dir, f"{self.log_name}.log")

        file_handler = TimedRotatingFileHandler(
            log_file,
            when=self.when,
            backupCount=self.backup_count,
            encoding='utf-8'
        )
        file_handler.setFormatter(formatter)
        self.logger.addHandler(file_handler)

        # 控制台处理器
        if self.console_output:
            console_handler = logging.StreamHandler()
            console_handler.setFormatter(formatter)
            console_handler.setLevel(logging.DEBUG)  # 设置控制台处理器只处理 DEBUG 级别及以上的日志
            console_handler.addFilter(lambda record: record.levelno == logging.DEBUG)  # 添加过滤器，确保只有 DEBUG 级别的日志输出到控制台
            self.logger.addHandler(console_handler)

    def get_logger(self):
        return self.logger


# 示例使用
if __name__ == '__main__':
    # 使用相对路径
    logger = Logger(root_path="../", log_name="power_load", level='debug').get_logger()
    logger.debug("这是一条 debug 级别的日志")
    logger.info("这是一条 info 级别的日志")
    logger.warning("这是一条 warning 级别的日志")
    logger.error("这是一条 error 级别的日志")
    logger.critical("这是一条 critical 级别的日志")